////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016-2018 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  camxstatscommon.h
/// @brief Stats common definitions
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef CAMXSTATSCOMMON_H
#define CAMXSTATSCOMMON_H

#include "camxtypes.h"
#include "camxpropertyblob.h"
#include "camxcsl.h"
#include "camxmetadatapool.h"
#include "camxnode.h"
#include "camxthreadmanager.h"
#include "camxhwcontext.h"
#include "camximagebuffer.h"
#include "camxpipeline.h"
#include "camxpropertyblob.h"
#include "camxhwdefs.h"

#include "chituningmodeparam.h"

CAMX_NAMESPACE_BEGIN

static const UINT32 MaxStatsProperties      = 20;   ///< Maximum number of properties statistics node dependent on
static const UINT32 MaxStatsDependentFences = 20;   ///< Maximum number of fences statistics node dependent on
static const UINT32 PreviousFrameDependency = 1;    ///< Define dependency to previous frame based one current frame
static const UINT32 NMinus2FrameDependency  = 2;    ///< Define dependency to n - 2 frame based one current frame

/// @brief The enum which defines the set/group of dependencies for property and buffer dependency.
enum class StatsDependencyGroup
{
    GROUP_EARLY,    ///< The group targeted for early processing
    GROUP_NORMAL    ///< The group targeted for normal processing
};

/// @brief Structure describing the property dependency and the set it belongs to.
struct StatsPropertyDependency
{
    PropertyID              property;   ///< Property dependency
    UINT64                  offset;     ///< Offset from implicit requestId on which wait is performed
    StatsDependencyGroup    group;      ///< The group to which
};

/// @brief Structure describing the property dependency and the set it belongs to.
struct StatsBufferDependency
{
    CSLFence*               phFences;           ///< Fences to wait for
    BOOL*                   pIsFenceSignaled;   ///< Pointer to fence variable whose signaled status is checked
    StatsDependencyGroup    group;              ///< The group to which fence belong to.
};

/// @brief This enum is used to index into node request dependency array to update any dependency not satisfied yet
enum NodeRequestDependencyIndex
{
    BufferDependencyIndex      = 0,    ///< Index to be used for Buffer dependency
    PropertyDependencyIndex,           ///< Index to be used for Property dependency
    CrossPropertyDependencyIndex       ///< Index to be used for cross pipeline Property dependency
};

/// @brief Structure describing the stats dependencies information.
struct StatsDependency
{
    INT32                   propertyCount;                      ///< Number of properties in this unit
    StatsPropertyDependency properties[MaxStatsProperties];     ///< Property dependencies in this unit
    INT32                   fenceCount;                         ///< Number of fences to wait for
    StatsBufferDependency   fences[MaxStatsDependentFences];    ///< Fences to wait for
};

/// @brief Structure describing the stats buffer information
struct StatsBufferInfo
{
    ISPStatsType    statsType;          ///< Stats type
    ImageBuffer*    pBuffer;            ///< Buffer associated with the stats coming in the port
    CSLFence*       phFences;           ///< Fences associated with the stats coming in the port
    BOOL*           pIsFenceSignaled;   ///< Pointer to fence variable whose signaled status is checked.
};

/// @brief This enum is to identify what kind of action Stats need to do when processing request
enum StatsAlgoAction
{
    StatsAlgoProcessRequest,                ///< Process regular request
    StatsAlgoProcessMapping,                ///< Process follower mapping
    StatsAlgoProcessSwitchingSlave,         ///< Process procedures that master is switching to slave. In this case, we do
                                            ///  process request first, then get peer info for new master
    StatsAlgoProcessSwitchingMaster         ///< Process procedures that slave is switching to master. In this case, we set
                                            ///  peer info first got from original master, then process request
};

/// @brief Structure describing the process request information.
struct StatsProcessRequestData
{
    Node*                   pNode;                                 ///< Node requesting processing
    UINT64                  requestId;                             ///< The unique frame number for this capture request
    INT32                   processSequenceId;                     ///< Identifier for the node to track its processing order
    UINT32                  pipelineDelay;                         ///< The pipeline delay of the CamX subsystem
    INT32                   bufferCount;                           ///< Buffer count
    StatsBufferInfo         bufferInfo[MaxStatsDependentFences];   ///< The buffer information of stats input buffer
    DependencyUnit*         pDependencyUnit;                       ///< Pointer to dependency list
    BOOL                    reportConverged;                       ///< Report that the algo is converged, even if it isn't
    ChiTuningModeParameter* pTuningModeData;                       ///< pointer to tuning mode data
    BOOL                    skipProcessing;                        ///< Flag to indicate skip processing and
                                                                   ///  publish previous frame control output
    StatsOperationMode      operationMode;                         ///< Indicates whether Fast or Normal Stats Processing
    StatsCameraInfo         cameraInfo;                            ///< Holds camera information
    StatsAlgoAction         algoAction;                            ///< The action Stats processor need to perform
    MultiRequestSyncData*   pMultiRequestSync;                     ///< Holds multi request sync data from higher layer
};

/// @brief Structure describing the callback information for initialization.
struct StatsInitializeCallback
{
    CHIAFALGORITHMCALLBACKS*    pAFCCallback;   ///< Stats algo entry pointer
    CHIAECALGORITHMCALLBACKS*   pAECCallback;   ///< Stats algo entry pointer
    CHIAWBALGORITHMCALLBACKS*   pAWBCallback;   ///< Stats algo entry pointer
    CHIAFDALGORITHMCALLBACKS*   pAFDCallback;   ///< Stats algo entry pointer
    CHIASDALGORITHMCALLBACKS*   pASDCallback;   ///< Stats algo entry pointer
    CHIPDLIBRARYCALLBACKS*      pPDCallback;    ///< PD Library entry pointer
};

/// @brief Structure describing the data types information for initialization.
struct StatsInitializeData
{
    Node*                   pNode;                  ///< Owning node
    MetadataPool*           pStaticPool;            ///< Static Property/metadata pool pointer
    MetadataPool*           pDebugDataPool;         ///< DebugData Property pool pointer
    ThreadManager*          pThreadManager;         ///< Pointer to thread manager.
    HwContext*              pHwContext;             ///< Pointer to HW context.
    BOOL                    isStatsNodeAvailable;   ///< Special purpose flags
    StatsInitializeCallback initializecallback;     ///< Algorithm callback pointer
    TuningDataManager*      pTuningDataManager;     ///< Tuning Data Manager
    Pipeline*               pPipeline;              ///< Pipeline to which the stats node belongs
    StatsStreamInitConfig   statsStreamInitConfig;  ///< Stats Stream Init Config
    ChiContext*             pChiContext;            ///< Chi Context information
    StatsCameraInfo         cameraInfo;             ///< Holds camera information
};

/// @brief Enumeration describing the worker thread job family
enum StatsJobFamily
{
    StatsJobFamilyInvalid   = 0,    ///< Invalid family
    StatsJobFamilyAll,              ///< All stats processor running in one worker thread
    StatsJobFamilyAecAwb,           ///< AEC and AWB stats processor jobs running in same worker thread
    StatsJobFamilyAfdAsd,           ///< AFD and ASD stats processor jobs running in same worker thread
    StatsJobFamilyCount             ///< Count of job family
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Class that implements statistics observer
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// NOWHINE CP017,CP018,CP044: Interface does not need copy/assignment/default overrides
class IStatsNotifier
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// NotifyJobProcessRequestDone
    ///
    /// @brief  Notifies the statistic node that a job from the worker thread is completed
    ///
    /// @param  requestId   Request Id
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult NotifyJobProcessRequestDone(
        UINT64          requestId) = 0;

protected:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ~IStatsNotifier
    ///
    /// @brief  Protected destructor to prevent accidental deletion of the observer.
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual ~IStatsNotifier() = default;
};

/// @brief Structure describing the data types information for initialization.
struct StatsNodeCreateData
{
    Node*           pNode;            ///< Pointer to the stats processing node
    IStatsNotifier* pStatsNotifier;   ///< Pointer to IStatsNotifier
    UINT32          instanceId;       ///< Instance Id
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Class that implements common stats utility functions.
///        This class contains only static functions and no state should be added to this class.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class StatsUtil
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetStatsType
    ///
    /// @brief  Map to ISP stats type from port id.
    ///
    /// @param  portId      port id associated with the stats
    ///
    /// @return ISPStatsType ISP stats type
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static ISPStatsType GetStatsType(
        UINT portId)
    {
        ISPStatsType statsType = ISPStatsTypeUndefined;

        switch (portId)
        {
            case StatsInputPortAWBBG:
                statsType = ISPStatsTypeAWBBG;
                break;
            case StatsInputPortBF:
                statsType = ISPStatsTypeBF;
                break;
            case StatsInputPortBHist:
                statsType = ISPStatsTypeBHist;
                break;
            case StatsInputPortHDRBE:
                statsType = ISPStatsTypeHDRBE;
                break;
            case StatsInputPortHDRBHist:
                statsType = ISPStatsTypeHDRBHist;
                break;
            case StatsInputPortIHist:
                statsType = ISPStatsTypeIHist;
                break;
            case StatsInputPortCS:
                statsType = ISPStatsTypeCS;
                break;
            case StatsInputPortRS:
                statsType = ISPStatsTypeRS;
                break;
            case StatsInputPortPDAFType3:
            case StatsInputPortRDIPDAF:
                statsType = ISPStatsTypeRDIPDAF;
                break;
            case StatsInputPortTintlessBG:
                statsType = ISPStatsTypeTintlessBG;
                break;
            default:
                CAMX_LOG_ERROR(CamxLogGroupStats, "Need to add new stats support");
                break;
        }

        return statsType;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// LoadAlgorithmLib
    ///
    /// @brief  Load algorithm library
    ///
    /// @param  pHandle             Output pointer to the loaded library's handle
    /// @param  pAlgorithmPath      Path to the algorithm library
    /// @param  pAlgorithmName      Name of algorithm
    /// @param  pFuncName           Name of the function
    ///
    /// @return custom loaded lib address
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static VOID* LoadAlgorithmLib(
        CamX::OSLIBRARYHANDLE* pHandle,
        const CHAR*            pAlgorithmPath,
        const CHAR*            pAlgorithmName,
        const CHAR*            pFuncName);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetDebugDataBuffer
    ///
    /// @brief  Returns the debug data associated with a given request ID
    ///
    /// @param  pDebugDataPool  Debug data property pool to get the debug data from
    /// @param  requestId       Request ID for which to obtain the debug data
    /// @param  tagId           Vendor tag associated with the debug data in interest
    /// @param  ppDebugDataOut  Debug data to be returned for the given request ID
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CamxResult GetDebugDataBuffer(
        MetadataPool*       pDebugDataPool,
        UINT64              requestId,
        UINT                tagId,
        DebugData**         ppDebugDataOut);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetStatsStreamInitConfig
    ///
    /// @brief  Retrieve the fast aec mode control data
    ///
    /// @param  pUsecasePool                Handle to Usecase property pool
    /// @param  pStatsStreamInitConfig      Output buffer to fill stats init config
    ///
    /// @return return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CamxResult GetStatsStreamInitConfig(
        MetadataPool*            pUsecasePool,
        StatsStreamInitConfig*   pStatsStreamInitConfig);
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Class that implements common stats Vendor Tag callback functions.
///        This is a singleton class
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class ChiStatsSession
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ChiStatsSession
    ///
    /// @brief  Constructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ChiStatsSession();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Initialize
    ///
    /// @brief  Initialize the class
    ///
    /// @param  pInitializeData   pointer to stats initialize data
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID Initialize(
        const StatsInitializeData* pInitializeData)
    {
        CAMX_ASSERT(NULL != pInitializeData);
        m_pNode                    = pInitializeData->pNode;
        m_pStaticPool              = pInitializeData->pStaticPool;
        m_pStatsProcessRequestData = NULL;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetStatsProcessorRequestData
    ///
    /// @brief  Sets the current processor request data
    ///
    /// @param  pStatsProcessRequestData Stats Processor current request data
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID SetStatsProcessorRequestData(
        const StatsProcessRequestData*    pStatsProcessRequestData)
    {
        CAMX_ASSERT(NULL != pStatsProcessRequestData);
        m_pStatsProcessRequestData = pStatsProcessRequestData;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetVendorTagBase
    ///
    /// @brief  Callback function to retrieve vendor tag base
    ///
    /// @param  pVendorTagBaseInfo  Pointer to input/output parameters to retrieve vendor tag base
    ///
    /// @return Success or failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDKResult GetVendorTagBase(
        CHIVENDORTAGBASEINFO* pVendorTagBaseInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FNGetMetadata
    ///
    /// @brief  The implementation for PFNNODEGETMETADATA defined in chinode.h
    ///
    /// @param  pMetadataInfo   Pointer to a structure that defines the list of metadata information requested by the node.
    ///
    /// @return CDKResultSuccess if success or appropriate error code.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDKResult FNGetMetadata(
        CHIMETADATAINFO* pMetadataInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FNSetMetadata
    ///
    /// @brief  The implementation for PFNNODESETMETADATA defined in chinode.h
    ///
    /// @param  pMetadataInfo Pointer to a structure that defines the list of metadata information published by the node.
    ///
    /// @return CDKResultSuccess if success or appropriate error code.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDKResult FNSetMetadata(
        CHIMETADATAINFO* pMetadataInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// QueryVendorTagLocation
    ///
    /// @brief  Callback function to retrieve vendor tag location
    ///
    /// @param  pSectionName    String section name
    /// @param  pTagName        String tag name
    /// @param  pTagLocation    Retrieved tagId
    ///
    /// @return Success or failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDKResult QueryVendorTagLocation(
        const CHAR* pSectionName,
        const CHAR* pTagName,
        UINT32*     pTagLocation);

private:


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetDynamicMetadata
    ///
    /// @brief  Gets a list of metadata information based on metadata tags.
    ///         The tag can be an Android tag or a vendor tag. If the metadata information associated with the tag is not
    ///         published, Chi returns those tags as unpublished when this function returns. The node can add them in the
    ///         dependency reporting during ChiNodeProcRequest().
    ///
    /// @param  pMetadataInfo   Pointer to a structure that defines the list of metadata information requested by the node.
    ///
    /// @return CDKResultSuccess if success or appropriate error code.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CDKResult GetDynamicMetadata(
        CHIMETADATAINFO* pMetadataInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetDynamicMetadata
    ///
    /// @brief  Sets a list of metadata information based on metadata tags.
    ///
    ///         The tag can be an Android tag or a vendor tag. When published, Chi driver will notify all other nodes that
    ///         reported these tags as dependencies.
    ///
    /// @param  pMetadataInfo Pointer to a structure that defines the list of metadata information published by the node.
    ///
    /// @return CDKResultSuccess if success or appropriate error code.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CDKResult SetDynamicMetadata(
        CHIMETADATAINFO* pMetadataInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetStaticMetadata
    ///
    /// @brief  Gets a list of metadata information based on metadata tags from static pool.
    ///
    /// @param  pMetadataInfo   Pointer to a structure that defines the list of metadata information requested by the node.
    ///
    /// @return Success or failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CDKResult GetStaticMetadata(
        CHIMETADATAINFO* pMetadataInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetStaticMetadata
    ///
    /// @brief  Sets a list of metadata information based on metadata tags into static pool.
    ///
    /// @param  pMetadataInfo Pointer to a structure that defines the list of metadata information published by the node.
    ///
    /// @return Success or failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CDKResult SetStaticMetadata(
        CHIMETADATAINFO* pMetadataInfo);

    MetadataPool*                   m_pStaticPool;              ///< Pointer to static metadata pool
    Node*                           m_pNode;                    ///< Pointer to owning Stats Node
    const StatsProcessRequestData*  m_pStatsProcessRequestData; ///< current stats processor request data

     // Do not implement the copy constructor or assignment operator
    ChiStatsSession(const ChiStatsSession&)             = delete;  ///< Disallow the copy constructor.
    ChiStatsSession& operator=(const ChiStatsSession&)  = delete;  ///< Disallow assignment operator.
};

CAMX_NAMESPACE_END

#endif // CAMXSTATSCOMMON_H
